package rhc.spider.util;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**信号注册
 * @author lenovo
 *
 */
public class AsyncSemaphoreUtil {

	/**
	 * 跟id相关联的信号
	 */
	private static final Map<Object,Semaphore> ID_SEMAPHORE=new HashMap<Object,Semaphore>();
	
	/**
	 * 内部锁
	 */
	private static final Object lock=new Object();
	
	
	/**创建一个含有 count 个信号的信号，如果是自己创建的且acquire为true则获取这些信号，不是自己创建的则直接返回
	 * @param id 信号id
	 * @param count 包含的信号个数
	 * @param acquire 是否获取
	 * @return
	 * @throws InterruptedException 
	 */
	public static boolean createSemaphore(Object id,int count,boolean acquire){
		if(haveSemaphoreId(id)){
			return false;
		}
		synchronized(lock){
			if(haveSemaphoreId(id)){
				return false;
			}
			Semaphore semaphore=new Semaphore(count);
			ID_SEMAPHORE.put(ID_SEMAPHORE, semaphore);
			if(acquire){
				try {
					semaphore.acquire(count);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
			}
			return true;
		}
	}
	
	/**从id获取count个信号，如果milis大于0则等待milis毫秒，否则一直等待
	 * @param id
	 * @param count
	 * @param milis
	 * @return
	 */
	public static boolean acquireSemaphore(Object id,int count,long milis){
		if(!haveSemaphoreId(id)){
			return false;
		}
		
		Semaphore semaphore=ID_SEMAPHORE.get(id);
		
		if(milis > 0){
			try {
				semaphore.tryAcquire(count, milis, TimeUnit.MILLISECONDS);
				return true;
			} catch (InterruptedException e) {
				return false;
			}
		}else{
			try {
				semaphore.acquire(count);
				return true;
			} catch (InterruptedException e) {
				return false;
			}
		}
	}
	
	/**一个id对应的信号释放count个信号
	 * @param id
	 * @param count
	 */
	public static void releaseSemaphore(Object id,int count){
		if(haveSemaphoreId(id)){
			return;
		}
		
		Semaphore semaphore=ID_SEMAPHORE.get(id);
		if(null != semaphore){
			semaphore.release(count);
		}
	}
	
	/**是否包含信号
	 * @param id
	 * @return
	 */
	private static boolean haveSemaphoreId(Object id){
		return ID_SEMAPHORE.containsKey(id);
	}
	
}
